package org.geekbang.thinking.in.spring.bean.lifecycle;

import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.concurrent.TimeUnit;

/**
 * Spring Bean 销毁生命周期
 *
 * @author: wangsiqi
 * @date: 2021/11/10
 */
public class BeanLifecycleDemo {

    public static void main(String[] args) throws InterruptedException {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 添加 BeanPostProcessor 实例
        beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());

        // 添加 DestructionAwareBeanPostProcessor 进行销毁回调
        beanFactory.addBeanPostProcessor(new MyDestructionAwareBeanPostProcessor());

        // 添加 CommonAnnotationBeanPostProcessor 解决 @PostConstructor 不能回调问题
        beanFactory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor());

        // 基于 XML 资源的 BeanDefinitionReader 实现
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // 加载 BeanDefinition
        String[] locations = new String[]{"META-INF/bean-constructor-dependency-injection-context.xml",
                "META-INF/dependency-lookup-context.xml"};
        int beanCounts = beanDefinitionReader.loadBeanDefinitions(locations);
        System.out.println("已加载  BeanDefinition 数量：" + beanCounts);

        // 查找 Bean
        User user = beanFactory.getBean("user", User.class);
        System.out.println("user: " + user);
        User superUser = beanFactory.getBean("superUser", User.class);
        System.out.println("superUser: " + superUser);

        // 构造器注入按照类型注入，resolveDependency
        UserHolder userHolder = beanFactory.getBean("userHolder", UserHolder.class);

        // 显示地执行 preInstantiateSingletons()
        // SmartInitializingSingleton 通常在 Spring Application 场景下使用
        beanFactory.preInstantiateSingletons();

        // 执行 Bean 销毁， Bean 销毁并不意味着被垃圾回收了
        beanFactory.destroyBean("userHolder", userHolder);

        System.out.println("userHolder: " + userHolder);

        // 彻底销毁 BeanFactory 里面的单例对象
        beanFactory.destroySingletons();
        // 强制 GC
        System.gc();
        // 等待一段时间
        TimeUnit.MILLISECONDS.sleep(1000);
        // 强制 GC
        System.gc();
    }


}
